package cn.lijiajia3515.cairo.auth.domain.mongo;

import cn.lijiajia3515.cairo.mongo.data.AbstractMongo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.mapping.MongoId;

import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Client
 */

@EqualsAndHashCode(callSuper = true)
@Data

@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder(toBuilder = true)
@Accessors(chain = true)
public class ClientMongo extends AbstractMongo {
	/**
	 * mongo id
	 */
	@MongoId
	private ObjectId _id;

	/**
	 * 唯一标识
	 */
	private String id;

	/**
	 * 应用标识
	 */
	private String appId;

	/**
	 * client id
	 */
	private String clientId;

	/**
	 * client secret
	 */
	private String clientSecret;

	/**
	 * 认证类型
	 */
	@Builder.Default
	private Set<String> clientAuthenticationMethods = Collections.emptySet();

	/**
	 * 授权类型
	 */
	@Builder.Default
	private Set<String> authorizationGrantTypes = Collections.emptySet();

	/**
	 * scope 值
	 */
	@Builder.Default
	private Set<String> scopes = Collections.emptySet();

	/**
	 * 基于浏览器认证 后的 跳转地址白名单
	 */
	@Builder.Default
	private Set<String> redirectUris = Collections.emptySet();

	/**
	 * 授权 设置
	 */
	@Builder.Default
	private ClientSettings clientSettings = new ClientSettings();

	/**
	 * token 设置
	 */
	@Builder.Default
	private TokenSettings tokenSettings = new TokenSettings();

	/**
	 * 其他属性配置
	 */
	@Builder.Default
	private Map<String, Object> attribute = new HashMap<>();

	/**
	 * 状态
	 */
	@Builder.Default
	private Boolean stat = false;

	@Data
	@Accessors(chain = true)
	@NoArgsConstructor
	@AllArgsConstructor
	@Builder
	public static class ClientSettings {
		/**
		 * 客户端标识符
		 */
		String clientId;

		/**
		 * TODO 我还不知道
		 */
		Boolean requireProofKey;

		/**
		 * 是否需确认授权
		 */
		Boolean requireAuthorizationConsent;
	}

	@Data
	@Accessors(chain = true)
	@NoArgsConstructor
	@AllArgsConstructor
	@Builder
	public static class TokenSettings {
		/**
		 * 访问令牌持续时间
		 */
		private Duration accessTokenTimeToLive;

		/**
		 * 是否重复使用刷新令牌
		 */
		private Boolean reuseRefreshTokens;

		/**
		 * 刷新令牌 持续时间
		 */
		private Duration refreshTokenTimeToLive;

		/**
		 * token 签名方式
		 */
		private String idTokenSignatureAlgorithm;
	}

	public static final Field FIELD = new Field();

	public static final class Field extends AbstractMongo.Field {
		private Field() {

		}
		public final String ID = field("Id");
		public final String CLIENT_ID = field("ClientId");
		public final String CLIENT_SECRET = field("ClientSecret");
		public final String CLIENT_AUTHENTICATION_METHODS = field("ClientAuthenticationMethods");
		public final String AUTHORIZATION_GRANT_TYPES = field("AuthorizationGrantTypes");
		public final String SCOPES = field("Scopes");
		public final String ATTRIBUTE = field("Attribute");

		public final String REDIRECT_URIS = field("RedirectUris");
		public final String CLIENT_SETTINGS = field("ClientSettings");
		public final String TOKEN_SETTINGS = field("TokenSettings");

		public final String ENABLED = field("Enabled");

		public static final class ClientSettings extends AbstractMongo.Field {
			public final String REQUIRE_PROOF_KEY = field("RequireProofKey");
			public final String REQUIRE_AUTHORIZATION_CONSENT = field("RequireAuthorizationConsent");
		}

		public static final class TokenSettings extends AbstractMongo.Field {
			public final String ACCESS_TOKEN_TIME_TO_LIVE = field("AccessTokenTimeToLive");
			public final String REUSE_REFRESH_TOKENS = field("ReuseRefreshTokens");
			public final String REFRESH_TOKEN_TIME_TO_LIVE = field("RefreshTokenTimeToLive");
			public final String ID_TOKEN_SIGNATURE_ALGORITHM = field("IdTokenSignatureAlgorithm");
		}
	}
}
